#include <math.h>

namespace Make3D{
    namespace core {
            namespace math {
        /// <summary>
        /// Interpolate two values using linear interpolation.
        /// </summary>
        /// <param name="a">A single-precision floating point number representing the first point.</param>
        /// <param name="b">A single-precision floating point number representing the second point.</param>
        /// <param name="x">A single-precision floating point number between 0 and 1 ( [0,1] ).</param>
        /// <returns>The interpolated value.</returns>
        template <class T>
        inline T LinearInterpolation(T a, T b, float x) {
            return a * (1 - x) + b * x;
        }
        /// <summary>
        /// Interpolate two values using cosine interpolation.
        /// </summary>
        /// <param name="a">A single-precision floating point number representing the first point.</param>
        /// <param name="b">A single-precision floating point number representing the second point.</param>
        /// <param name="x">A single-precision floating point number between 0 and 1 ( [0,1] ).</param>
        /// <returns></returns>
        template <class T>
        inline T CosineInterpolation(T a, T b, float x) {
            float ft = (float)(x * (float)Math.PI);
                   x = (1.0f - (float)System.Math.Cos(ft)) * 0.5f;
                   return a * (1 - x) + b * x;
        }
        /// <summary>
        /// Interpolate two values using cubic interpolation.
        /// </summary>
        /// <param name="a">A single-precision floating point number representing the first point.</param>
        /// <param name="b">A single-precision floating point number representing the second point.</param>
        /// <param name="x">A single-precision floating point number between 0 and 1 ( [0,1] ).</param>
        /// <returns></returns>
        template <class T>
        inline T CubicInterpolation(T a, T b, float x) {
            float fac1 = 3 * (float)pow(1 - x, 2) - 2 * (float)pow(1 - x, 3);
            float fac2 = 3 * (float)pow(x, 2) - 2 * (float)pow(x, 3);
            return a * fac1 + b * fac2;
        }
    }
    }

    }

